using Basis;
using DG.Tweening;
using UnityEngine;
using UnityEngine.EventSystems;

namespace NL.Advanced
{
    public interface ICameraOwner
    {
        GameObject gameObject { get; }
        bool Locked { set; }
        bool Dragable { get; set; }
        bool Zoomable { get; set; }

        bool Ready { get; }
    }
    public partial class CameraBase : MonoBehaviour, ICameraOwner
    {

        //相机锁止控制.
        public bool Locked
        {
            set
            {
                _Dragable = _Zoomable = !value;
            }
        }


        public bool Dragable { get => _Dragable && !IsAniming && (_CameraParent == null ? true : _CameraParent.Dragable); set => _Dragable = value; }
        public bool Zoomable { get => _Zoomable && !IsAniming && (_CameraParent == null ? true : _CameraParent.Zoomable); set => _Zoomable = value; }

        public bool Ready { get; set; }

        [Header("相机锁止状态:是否可以拖拽;是否可以缩放")]
        [SerializeField] protected bool _Dragable = true;
        [SerializeField] protected bool _Zoomable = true;

        [Header("移动靠自己..方向靠Forward")]
        public Transform Forward;
        public Camera MainCamera;

        [Header("拖拽,阻尼系数(0~1) ;缩放步进系数")]
        public float CameraDragCorrectly = -1f;
        public float SpeedDamping = 0.1f;
        public float CameraZoomCorrectly = 3.0f;


        [Header("相机拖拽移动或者弹性回归速度最大值")]
        public float MovingSpeedByScreenMax = 2000;
        public Vector2 MovingSpeedByScreen;

        [Header("相机回归得弹性值;指数;触发回归得边缘宽度(百分比)")]
        public bool OpenSpringBack = true;
        public float Spring = 100;
        public float SpringExponent = 3f;
        public float SpringWidth = 0.2f;



        // 相机 .运行时参数.. 同时初始化得时候将设计时得数据备份为DefaultConfig.
        [Header("相机配置参数......")]
        public CameraConfigData Config;


        //默认相机参数 来源于 设计时得 Config;
        protected CameraConfigData DefaultConfig;


        public bool IsRouting = false;

        // [Header("有效区..")]
        public IBoundOwner BoundOwner;
        ICameraOwner _CameraParent;



        protected virtual void Awake()
        {
            Ready = false; Invoke("_ReadyLater", 2f);

            if (Forward == null) Forward = transform;
            //将配置备份..记录为默认 相机配置..
            //DefaultConfig 默认相机参数
            //Config 当前相机参数.
            //DefaultConfig = CloneTrans<CameraConfigData, CameraConfigData>.Clone(Config);

            _CameraParent = transform.parent != null ? transform.parent.GetComponentInParent<ICameraOwner>() : null;

            _InitCorner();

        }
        public CameraBase SetBound(IBoundOwner bound)
        {
            BoundOwner = bound;

            return this;
        }


        public void ConfigRestore()
        {

            Config = DefaultConfig;

            _Dragable = Config.Dragable;
            _Zoomable = Config.Zoomable;

            return;

        }
        public CameraBase SetDefault(CameraConfigData config)
        {
            DefaultConfig = CloneTrans<CameraConfigData, CameraConfigData>.Clone(Config);
            return this;
        }
        CameraConfigData _LastConfig;
        public void ConfigUse(CameraConfigData config, bool anim = true, GameObject focuswho = null)
        {
            //if (Config != null && Config.FocusTarget != null)
            //{
            //    LOG.Add($"Camera base config use : target not null oldTarget:{Config.FocusTarget} newTarget:{config.FocusTarget} who:{focuswho}");
            //    FollowEnd();
            //}

            //先把之前得 配置记录..
            _LastConfig = CloneTrans<CameraConfigData, CameraConfigData>.Clone(Config);


            //相机参数套件赋值...
            Config = config;

            _Dragable = Config.Dragable;
            _Zoomable = Config.Zoomable;


            // 处理相机位置,旋转以及动画.
            float H = config.HighDefault > 0 ? config.HighDefault : transform.position.y;

            // 目标旋转向量
            Quaternion QQ = Quaternion.Euler(config.Pitch, config.Yaw, 0);


            ///focuswho 优先使用 传参---->Config 得设计---> 父节点原点
            if (focuswho == null && Config.FocusTarget != null)
            {
                focuswho = Config.FocusTarget;
            }


            // 获取 焦点位置 
            Vector3 focuspos = focuswho != null ? focuswho.transform.position : transform.parent.position;

            focuspos += config.FocusTargetOffset;

            //计算 相机位置.
            Vector3 lookat = _Line_PANEL(focuspos, QQ * Vector3.back, Vector3.up, Vector3.up * H);



            //相机默认位置. 在没明确焦点目标得时候.用有效得位置信息.
            if (focuswho == null && config.DefaultPosition.w > 0)
            {
                lookat = config.DefaultPosition;
            }


            // 响应相机得各类参数 设置..

            // 处理 包含相机运动...........
            MovingSpeedByScreen = Vector2.zero;

            if (anim)
            {
                IsAniming = true;
                MainCamera.DOFieldOfView(config.FOV, config.duration * 0.3f).SetEase(config.Ease).SetDelay(config.duration * 0.9f);
                Forward.DOLocalRotateQuaternion(QQ, config.duration).SetEase(config.Ease);
                transform.DOMove(lookat, config.duration).SetEase(config.Ease).OnComplete(() =>
                {
                    IsAniming = false;
                });

                //如果开启了 入境禁用输入事件..
                if (config.EventDisableDuration)
                {
                    // if(InputController.INSTANCE!=null)  InputController.INSTANCE.gameObject.EVENTProtect(config.duration+0.25f);
                    if (EventSystem.current != null) EventSystem.current.gameObject.EVENTProtect(config.duration + 0.25f);
                }


            }
            else
            {
                MainCamera.fieldOfView = config.FOV;
                Forward.localRotation = QQ;
                transform.position = lookat;

            }




            OnConfigUse();

        }
        void _ReadyLater()
        {
            Ready = true;
        }
        public bool IsAniming = false;
        protected virtual void OnConfigUse()
        {

        }
        //有聚焦对象的时候 更新聚焦...
        void _UpdateForFocus()
        {
            float H = Config.HighDefault > 0 ? Config.HighDefault : transform.position.y;

            // 目标旋转向量
            Quaternion QQ = Quaternion.Euler(Config.Pitch, Config.Yaw, 0);

            // 获取 焦点位置 
            Vector3 focuspos = Config.FocusTarget.transform.position;

            focuspos += Config.FocusTargetOffset;

            //计算 相机位置.
            Vector3 lookat = _Line_PANEL(focuspos, QQ * Vector3.back, Vector3.up, Vector3.up * H);


            transform.position = Vector3.Slerp(transform.position, lookat, SpeedDamping);
        }
        //有聚焦对象的时候 更新聚焦...
        void _UpdateForFollow()
        {
            float H = Config.HighDefault > 0 ? Config.HighDefault : transform.position.y;

            // 目标旋转向量
            Quaternion QQ = Quaternion.Euler(Config.Pitch, Config.Yaw, 0);

            // 获取 焦点位置 
            Vector3 focuspos = FollowTarget.position;

            focuspos += Config.FocusTargetOffset;

            //计算 相机位置.
            Vector3 lookat = _Line_PANEL(focuspos, QQ * Vector3.back, Vector3.up, Vector3.up * H);


            transform.position = Vector3.Slerp(transform.position, lookat, SpeedDamping);
        }
        protected virtual void Update()
        {
            if (IsAniming && !Ready) return;

            if (_CameraParent != null && !_CameraParent.Ready)
                return;
            if (OpenSpringBack)
            {
                //判断视场越界 修改为 CamerCorner去自主执行..
                // _UpdateViewBounds();

                ///
                ///             
                ///         ________________________    相机视场边界.....
                ///         |         弹性边缘       |
                ///         |     _____________     |
                ///         |    |            |     |
                ///         |    |            |     |
                ///         |    |            |     |
                ///         |    |            |     |
                ///         |    |            |     |
                ///         |    |            |     |
                ///         |    |            C   P |
                ///         |    |            |     |    
                ///         |    |            |     |
                ///         |    |            |     |
                ///         |    |____________|     |
                ///         |                       |
                ///         |                       |
                ///         -------------------------
                ///
                ///   当相机某个Corner位于 P点....计算最近点 C ; Offser=P->C; 统计各个Corner得Offset
                ///   合成后得 Offset 根据计算公式  y = s*Offset^e    s=Spring  e=SpringExponent;
                ///   获取 y 转换成相机基于屏幕得移动速度 MovingSpeedByScreen
                ///


                //收集 视场越界 得弹性回归值...
                if (ViewBoundCorners != null && ViewBoundCorners.Length > 0)
                {
                    Vector3 offset = Vector3.zero;
                    foreach (var corner in ViewBoundCorners)
                    {
                        offset += corner.Offset;
                    }
                    if (offset.magnitude > 0.1f)
                    {
                        //offset= transform.InverseTransformVector(offset);
                        // 世界方向 转换为 屏幕坐标系..
                        var dir = Forward.InverseTransformDirection(offset).normalized;

                        ///                     SpringExponent
                        ///       speed= offset^               *Spring
                        ///
                        MovingSpeedByScreen = new Vector2(-dir.x, -dir.z) * Mathf.Pow(offset.magnitude, SpringExponent) * Spring;
                        //if(MovingSpeedByScreen.magnitude>99999)

                        //   LOG.Add($"[CameraBase.Update]:MovingSpeedByScreen={MovingSpeedByScreen}");
                    }
                }


            }
        }


        /// <summary>
        /// 在FixedUpdate 处理相机移动的阻尼.
        /// </summary>
        public float UnSpeedWhenFollow = 10f;
        protected virtual void FixedUpdate()
        {

            if (IsAniming && !Ready) return;

            if (_CameraParent != null && !_CameraParent.Ready)
                return;

            if (Input.GetMouseButton(0))
                return;


            float mag = MovingSpeedByScreen.magnitude;

            //需要跟随.并且低移动速度的时候 取消移动 
            if (Config.FocusNeed && mag < UnSpeedWhenFollow)
            {
                MovingSpeedByScreen = Vector2.zero; mag = 0;
            }

            // 是否要处理 位置移动
            if (mag > 0.3f)
            {
                // 移动速度超过最大值?
                if (MovingSpeedByScreen.magnitude > MovingSpeedByScreenMax)
                {
                    MovingSpeedByScreen = MovingSpeedByScreen.normalized * MovingSpeedByScreenMax;
                }

                //按照移动速度移动
                MoveByScreent(MovingSpeedByScreen * Time.fixedDeltaTime);

                //阻尼...
                MovingSpeedByScreen = Vector3.Slerp(MovingSpeedByScreen, Vector3.zero, SpeedDamping);

            }
            else if (FollowNeed)            // 需要跟随的时候??
            {
                MovingSpeedByScreen = Vector2.zero;

                _UpdateForFollow();

            }
            else if (Config.FocusNeed)            // 需要聚焦的时候??
            {
                MovingSpeedByScreen = Vector2.zero;

                _UpdateForFocus();

            }
        }

    }
}

